﻿using System;
using System.Collections.Generic;
using System.Text;

namespace X3DLib
{
    namespace FireScriptFacotr
    {
        /// <summary>
        /// 平常火类
        /// </summary>
        public class FireNormalScript : ScriptContent
        {
            /// <summary>
            /// 初始化空闲节点索引
            /// </summary>
            /// <returns></returns>
            public string init_freepartarray()
            {
                return "function init_freepartarray()//remember the free particle to help find out them index\n"
                        + "{\n"

                            + "for(i=1;i<nodeNum;i++)\n"
                            + "{\n"
                                + "FreePartArray[i-1]=i;\n"
                                + "FreeNum=nodeNum-1;\n"
                            + "}\n"

                        + "}\n";

            }
            /// <summary>
            /// 点一个火苗
            /// </summary>
            /// <returns></returns>
            public string fire_burn()
            {
                return "function fire_burn()\n"
                        + "{\n"
                            + "y=Math.random();\n"
                            + "x=(1-y)*range[0]*(Math.random()-0.5);\n"
                            + "z=(1-y)*range[2]*(Math.random()-0.5);\n"
                            + "\n"
                            + "num=Math.round(Math.random()*100+100);\n"
                            + "temp=(FreeNum>=num?num:FreeNum);\n"
                            + "//temp=FreeNum*0.9;\n"
                            + "count=0;\n"
                            + "index=0;\n"
                            + "while( count< temp )\n"
                            + "{\n"
                                + "index=FreePartArray[FreeNum-1];\n"
                                + "//set size\n"
                                + "nodes[index].size[0]=nodes[index].size[1]=nodes[index].size[2]=nodes[0].size*(0.6+Math.random()*0.3);\n"
                                + "//set position\n"
                                + "nodes[index].position[0]=x;\n"
                                + "nodes[index].position[1]=y*range[1]*0.4/2;\n"
                                + "nodes[index].position[2]=z;\n"
                                + "//set speed\n"
                                + "nodes[index].velocity[0]=(Math.random()-0.5);\n"
                                + "nodes[index].velocity[1]=Math.random()*4;\n"
                                + "nodes[index].velocity[2]=(Math.random()-0.5);\n"
                                + "//set transparency\n"
                                + "nodes[index].transparency=Math.random()*0.1+0.4;\n"
                                + "//set age\n"
                                + "nodes[index].age=0;\n"
                                + "//set color\n"
                                + "if(y>0.8)//when fire in center bright color\n"
                                + "{\n"
                                    + "if(Math.random()>0.3)	//yellow\n"
                                    + "{\n"
                                        + "nodes[index].diffuseColor[0]=Math.random()*0.2+0.8;\n"
                                        + "nodes[index].diffuseColor[1]=nodes[index].diffuseColor[2]=0.1*Math.random();\n"
                                        + "\n"
                                        + "nodes[index].specularColor[0]=nodes[index].specularColor[1]=nodes[index].specularColor[2]=Math.random()*0.2+0.8;\n"
                                        + "\n"
                                        + "nodes[index].emissiveColor[0]=nodes[index].emissiveColor[1]=Math.random()*0.2+0.8;\n"
                                        + "nodes[index].emissiveColor[2]=0;\n"
                                    + "}\n"
                                    + "else  //white\n"
                                    + "{\n"
                                        + "nodes[index].diffuseColor[0]=nodes[index].diffuseColor[1]=nodes[index].diffuseColor[2]=Math.random()*0.2+0.4;\n"
                                        + "\n"
                                        + "nodes[index].specularColor[0]=nodes[index].specularColor[1]=Math.random()*0.2+0.8;\n"
                                        + "nodes[index].specularColor[2]=Math.random()*0.01;\n"
                                        + "\n"
                                        + "nodes[index].emissiveColor[0]=nodes[index].emissiveColor[1]=nodes[index].emissiveColor[2]==Math.random()*0.2+0.8;\n"
                                    + "}\n"
                                + "}\n"
                                + "else\n"
                                + "{\n"
                                    + "nodes[index].diffuseColor[0]=color[0]+Math.random()*0.16*(Math.random()-0.5);\n"
                                    + "nodes[index].diffuseColor[1]=color[1]+Math.random()*0.16*(Math.random()-0.5);\n"
                                    + "nodes[index].diffuseColor[2]=color[2]+Math.random()*0.16*(Math.random()-0.5);\n"
                                    + "\n"
                                    + "nodes[index].specularColor[0]=1;\n"
                                    + "nodes[index].specularColor[1]=1;\n"
                                    + "nodes[index].specularColor[2]=0;\n"
                                    + "\n"
                                    + "nodes[index].emissiveColor[0]=color[0]*0.8+(Math.random()-0.5)*0.2;\n"
                                    + "nodes[index].emissiveColor[1]=color[1]*0.6+(Math.random()-0.5)*0.4;\n"
                                    + "nodes[index].emissiveColor[2]=color[2]*0.4+(Math.random()-0.5)*0.6;\n"
                                + "}\n"
                                + "//set shinness\n"
                                + "nodes[index].shininess=1;\n"
                                + "//set ambienIntensity\n"
                                + "nodes[index].ambientIntensity=1;\n"
                                + "count++;\n"
                                + "FreeNum--;\n"
                            + "}\n"
                        +"}\n";
            }
            public string touch_position()
            {
                return "function touch_position(value)\n"
                        + "{"

                        + "}\n";
            }
            /// <summary>
            /// 创建火脚本的主函数
            /// </summary>
            /// <returns></returns>
            public string normalFireMain()
            {
                return this.contextHead()
                    +"\n"
                    +this.initialize("")
                    +"\n"
                    +this.init_environment(""
                                            + "nodes=group.children;	//get nodes including one evironment and num of particles ,also one waterbase and one touch\n"
                                            + "nodeNum=nodes.length-1; //get the nodes count\n"
                                            + "color=nodes[0].color;	//get the evironment color setting\n"
                                            + "range=nodes[0].range;	//get the range of water\n"
                                            + "life=nodes[0].life;	    //get particles' life\n"
                                            + "gravity=nodes[0].gravity;//get evironment's gravity\n"
                                            + "wind=nodes[0].wind;	    //get evironment's wind\n"
                                            )
                    +"\n"
                    +this.init_freepartarray()
                    +"\n"
                    +this.init_particles(""
                                        + "init_freepartarray();\n"
                                        + "for(i=1;i<nodeNum;i++)\n"
                                        + "{\n"
                                            + "nodes[i].transparency=1;//make all particle disappearanced\n"
                                        + "}\n"
                                        + "for(i=1;i<nodeNum/100;i++)\n"
                                            + "fire_burn();\n"
                                        )
                    +"\n"
                    +this.fire_burn()
                    +"\n"
                    +this.update_particles(""
                                            + "for(i=1;i<nodeNum;i++)\n"
                                            + "{\n"
                                                + "if(nodes[i].transparency==1)continue;\n"
                                                + "nodes[i].age++;\n"
                                                + "//set velocity\n"
                                                + "if(nodes[i].age>10)\n"
                                                + "{\n"
                                                    + "nodes[i].velocity[0]*=1+(wind[0]/nodes[i].velocity[0]);\n"
                                                    + "nodes[i].velocity[1]*=1+(wind[1]/nodes[i].velocity[1]);\n"
                                                    + "nodes[i].velocity[2]*=1+(wind[2]/nodes[i].velocity[2]);\n"
                                                + "}\n"
                                                + "//set shininess\n"
                                                + "nodes[i].shininess-=0.01;\n"
                                                + "//set transparency\n"
                                                + "nodes[i].transparency+=0.005*Math.random();\n"
                                                + "//set size\n"
                                                + "nodes[i].size[2]-=nodes[0].size*0.02;\n"
                                                + "nodes[i].size[0]=nodes[i].size[1]=nodes[i].size[2];\n"
                                                + "//(v(t+1)+0.5*g*(t+1)^2) - (vt+0.5*g*t^2)=v+0.5*g*(2*t+1)=v+g*(t+0.5) //t+1->t+0.02\n"
                                                + "nodes[i].position[0]+=( (nodes[i].velocity[0]+wind[0])+(gravity[0]*0.02)*(nodes[i].age+0.5) )*0.02;\n"
                                                + "nodes[i].position[1]+=( (nodes[i].velocity[1]+wind[1])-(gravity[1]*0.02)*(nodes[i].age+0.5) )*0.02*Math.random();\n"
                                                + "nodes[i].position[2]+=( (nodes[i].velocity[2]+wind[2])+(gravity[2]*0.02)*(nodes[i].age+0.5) )*0.02;\n"
                                                + "//update color\n"
                                                + "if(nodes[i].position[1]>range[1]*(Math.random()*0.1+0.6) || Math.abs(nodes[i].position[0])>0.5*range[0]*(Math.random()*0.1+0.6) || Math.abs(nodes[i].position[2])>0.5*range[2]*(Math.random()*0.1+0.6) )\n"
                                                + "{\n"
                                                    + "nodes[i].diffuseColor[2]-=0.1;\n"
                                                    + "nodes[i].diffuseColor[0]=nodes[i].diffuseColor[1]=nodes[i].diffuseColor[2];\n"
                                                    + "\n"
                                                    + "nodes[i].emissiveColor[2]-=0.1;\n"
                                                    + "nodes[i].emissiveColor[0]=nodes[i].emissiveColor[1]=nodes[i].emissiveColor[2];\n"
                                                + "}\n"
                                                + "else\n"
                                                + "{\n"
                                                    + "nodes[i].diffuseColor[0]+=Math.random()*0.16*(Math.random()-0.5);\n"
                                                    + "nodes[i].diffuseColor[1]+=Math.random()*0.08*(Math.random()-0.5);\n"
                                                    + "nodes[i].diffuseColor[2]+=Math.random()*0.04*(Math.random()-0.5);\n"
                                                    + "\n"
                                                    + "nodes[i].emissiveColor[0]+=Math.random()*0.16*(Math.random()-0.5);\n"
                                                    + "nodes[i].emissiveColor[1]+=Math.random()*0.08*(Math.random()-0.5);\n"
                                                    + "nodes[i].emissiveColor[2]+=Math.random()*0.04*(Math.random()-0.5);\n"
                                                + "}\n"
                                                + "if(nodes[i].position[1]<0.1||nodes[i].age>20)\n"
                                                + "{\n"
                                                    + "//release particle and add it into freeparticles\n"
                                                    + "FreeNum++;\n"
                                                    + "FreePartArray[FreeNum-1]=i;\n"
                                                    + "nodes[i].transparency=1;\n"
                                                + "}\n"
                                                + "//set wind change\n"
                                                + "//wind[0]+=(Math.random()-0.5)*wind[0]*(0.02*Math.random());\n"
                                                + "//wind[1]+=(Math.random()-0.5)*wind[1]*(0.02*Math.random());\n"
                                                + "//wind[2]+=(Math.random()-0.5)*wind[2]*(0.02*Math.random());\n"
                                                + "//add fire_burn\n"
                                                + "if(Math.random()>0.5)\n"
                                                    + "fire_burn();\n"
                                            + "}\n" 
                                           )
                    +"\n"
                    +this.update("")
                    +"\n"
                    +this.start("")
                    +"\n"
                    +this.touch_change(""
                                        + "color[0]=Math.random();\n"
                                        + "color[1]=Math.random();\n"
                                        + "color[2]=Math.random();\n"
                                        )
                    +"\n"
                    +this.touch_position()
                    +"\n"
                    +this.contextEnd();
            }
        }
        /// <summary>
        /// 烟花类
        /// </summary>
        public class FireFlowerScript : ScriptContent
        {
            public string flowerFireMain()
            {
                return null;
            }
        }
    }
}
